package com.googlecode.theta.server;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptableObject;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

public class ScriptEngine {
  private final Context context = ContextFactory.getGlobal().enterContext();
  private final ScriptableObject globalScope = getContext().initStandardObjects();

  public ScriptEngine() {

  }

  public void run(String fileName) {
    try {
      InputStream stream = new FileInputStream(fileName);
      Reader reader = new InputStreamReader(stream);

      getContext().evaluateReader(globalScope, reader, fileName, 1, null);

      reader.close();
      stream.close();
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }

  public Object executeString(String code) {
    return getContext().evaluateString(globalScope, code, "<command>", 1, null);
  }

  public void addObject(String name, Object instance) {
    Object wrapped = Context.javaToJS(instance, globalScope);
    ScriptableObject.putProperty(globalScope, name, wrapped);
  }

  public Context getContext() {
    return ContextFactory.getGlobal().enterContext();
  }

  public ScriptableObject getGlobalScope() {
    return this.globalScope;
  }

  public Object invoke(String methodName, Object[] parameters) {
    Object m = globalScope.get("main", globalScope);
    if (m instanceof Function) {
      Object result = ((Function) m).call(getContext(), globalScope, globalScope, parameters);
      return result;
    } else {
      throw new RuntimeException("Method not found.");
    }
  }
}
